/**
 * Controller para pruebas de generacion de vistas.
 */
package hce

import se.acode.openehr.parser.*
import org.openehr.am.archetype.Archetype

import hce.HceService

import archetype_repository.ArchetypeManager
import hce.ArchetypeService
import templates.TemplateManager
import templates.tom.* // Template

import events.*

import com.thoughtworks.xstream.XStream

import hce.core.composition.*

import hce.core.common.archetyped.Locatable

//TEST BINDER
import binding.BindingAOMRM

/**
 * @author Pablo Pazos Gutierrez (pablo.swp@gmail.com)
 */
class GuiGenController {

    def archetypeService
    def hceService
    
    def index = {
        //redirect(action:'listarArquetipos')
        redirect(action:'listarTemplates')
    }
    
    // Esta accion es de prueba, la lista de templates para completar se hace desde trauma.registroClinico,
    // que carga los templates que se llenan (no las pruebas) y su orden para armar la pantalla 5.1.
    def listarTemplates = {

        // FIXME: Ahora listo los templates asi nomas, puede haber subdirectorios.
        def path = "templates/hce/trauma"
        //def path = "templates/hce/trauma/evaluacion/evaluacion_primaria"
        def p = ~/.*\.xml/
        def templatesNames = []
        new File( path ).eachFileMatch(p)
        { f ->
           templatesNames << f.name - ".xml" // Solo el id, no necesito la extension del archivo
        }
         
        render(view:"listarTemplates", model:[templateNames: templatesNames])
    }
    
    // in: template
    def generarTemplate = {
       
       EventManager.getInstance().handle("pre_gui_gen", params)
       
       
       // DEBE haber un episodio seleccionado para poder asociar el registro clinico.
       if (!session.traumaContext?.episodioId)
       {
           flash.message = 'trauma.list.error.noEpisodeSelected'
           redirect(controller:'trauma', action:'list')
           return
       }
       
       // Model: Paciente del episodio seleccionado
       def composition = Composition.get( session.traumaContext.episodioId )
       def patient = hceService.getPatientFromComposition( composition )
       
       // Secciones predefinidas para seleccionar registro clinico
       def sections = []
       grailsApplication.config.hce.emergencia.compositions.trauma.keySet().each { sectionPrefix ->
          sections << sectionPrefix
       }
       
       // Subsections de la section seleccionada
       def subsections = []
       def subSectionPrefix = params.templateId.split("-")[0]
       grailsApplication.config.hce.emergencia.compositions.trauma."$subSectionPrefix".each { subsection ->
          subsections << subSectionPrefix + "-" + subsection
       }
       
       //println "subSectionPrefix: " + subSectionPrefix
       //println "subsections: " + subsections

       def templateId = params.templateId // es el nombre del archivo
       Template template = TemplateManager.getInstance().getTemplate( templateId )
       
       def fullUri = grailsAttributes.getViewUri('../hce/'+params.templateId, request)
       
       //println fullUri
       //println grailsAttributes.pagesTemplateEngine.getResourceForUri(fullUri)

       def resource = grailsAttributes.pagesTemplateEngine.getResourceForUri(fullUri)
       if ( resource && resource.file && resource.exists() )
       {
           println 'vista estatica'
           
           EventManager.getInstance().handle("post_gui_gen", params)
           
           render( view: '../hce/'+params.templateId,
                   model: [
                           patient: patient,
                           template: template,
                           sections: sections,
                           subsections: subsections,
                           episodeId: session.traumaContext?.episodioId
                          ] )
           return
       }
       else
       {
           println 'vista dinamica'

           EventManager.getInstance().handle("post_gui_gen", params)

           def root = "templates/hce/trauma"
           //def templateId = "test_prescripcion" // TODO: se debe pasar por parametro
           //def templateId = "test_a1_a2" // TODO: se debe pasar por parametro
    //       def templateId = "/evaluacion/evaluacion_primaria/columna_vertebral"
           
           def filename = root +"/"+templateId+".xml"
           
           // OK
           //XStream xstream = new XStream()
           //println xstream.toXML(template) + "\n\n"
           //println "templateID: " + template.id
           
           // TODO: buscar si existe la vista para el template, y si no existe ir a la generacion dinamica.
           
           return [archetypeService: archetypeService,
                   template: template,
                   patient: patient,
                   sections: sections,
                   subsections: subsections,
                   episodeId: session.traumaContext?.episodioId]
       }
           
    } // generateTemplate
    
    /**
     * 
     */
    def listarArquetipos = {
   
       println "===" + archetypeService + "==="
            
       // Test archetype manager
       //def manager = ArchetypeManager.getInstance()
       //manager.loadAll()
       //println manager
       // /Test archetype manager
      
       // FIXME: cambie la estructura de arquetipos a la que usa openEHR, asi que habria que listar subdirectorios.
       //def path = "archetypes/ehr/entry/evaluation"
       //def path = "archetypes/ehr/entry/action"
       //def path = "archetypes/ehr/cluster"
       def path = "archetypes/ehr/section"
       def p = ~/.*\.adl/
       def arqsNames = []
       new File( path ).eachFileMatch(p)
       { f ->
          arqsNames << f.name - ".adl" // Solo el id, no necesito la extension del archivo
       }
        
       render(view:"listarArquetipos", model:[arqNames:arqsNames])
    }
    
    /**
     * Prueba para poder ver los arquetipos que estan cargados en cache.
     */
    def loadedArchetypes = {
       def manager = ArchetypeManager.getInstance()
       render( manager.toString() )
    }
    
    /**
     * in: archetypeId
     */
    def generar = {
           
       //println "===" + archetypeService + "==="
   
       // FIXME: ahora es con arquetipos para probar, pero
       //        deberia ser con templates!
       def archetypeId = params.archetypeId
       
       log.debug("generar: " + params.archetypeId)
       
       // Test archetype manager
       def manager = ArchetypeManager.getInstance()
       Archetype archetype = manager.getArchetype( archetypeId )
       // /Test archetype manager
       
       
       render(view:"generar", model:[archetype:archetype, archetypeService:archetypeService])
    }
    
    def save = {
    
       // Deberian venir todas las paths definidas en el template que use
       // para crear la vista, y complementarse con las paths que se definieron
       // en el template que no se mostraran en la vista, por ejemplo, para
       // casos de valores asumidos, donde el usuario no puede ingresar otra
       // cosa que lo que dice el template.
       // Los valores asumidos del template pueden derivarse de los arquetipos,
       // pero seran muy pocos arquetipos los que definan estos valores, porque
       // deben ser de uso general.
       
       // TODO: ver que transformaciones hay definidas para los paths->data 
       // submiteados y transformar los datos que tengan transformaciones
       // definidas y darle a Lea todo listo para guardar
       
       // TODO: las transformaciones de unidades deberian hacerse por el Measurement Service
       
       //println params.getClass()
       
       
       // Veo si vienen archivos
       def files = request.getFileMap()
       
       println "VIENEN ARCHIVOS: " + files
       println "+++++++++++++++++++++++++++++++++++++++++++++++++++"
       
       
       def template = TemplateManager.getInstance().getTemplate( params.templateId )
       def transformations = template.getTransformations()
       
       //println "Hay " + transformations.size() + " transformaciones" 
       
       transformations.each { transform ->
       
           //println "Transform: " + transform.operation + " " + transform.operand
       
           // archetypeId+path
           if ( params.containsKey( transform.owner.owner.id + transform.path) )
           {
               // Solo puede transformar un number
               // Number no tiene funcion para pasar de un string a number
               // Uso Float para todo // FIXME: puede dar problemas si el valor no es float en el arquetipo.
               
               try // por si el numero no viene tengo un error, deberia meter un error en errors2 del binder si es que el valor era obligatorio: DE ESO SE ENCARGA EL BINDER!
               {
                   def oldValue = Float.valueOf( params.(transform.owner.owner.id+transform.path) )
                   def newValue = transform.process( oldValue )
                   
                   // FIXME: en la desconversion para el show, si ahora ingreso 10 se guarda 0.16666666666,
                   //        en la inversa, 0.1666666666 da 9.99996, asi que en la desconversion
                   //        deberia intentar hacer redondeo para mostrar.
                   //        Preguntar en la lista de OpenEHR si alguien supo resolver esto de una forma que no sea
                   //        cambiando el tipo del Quantity por 2 campos individuales en un cluster.
                   
                   println "Old: " + oldValue + ", New: " + newValue
                   
                   params.(transform.path) = newValue
               }
               catch (Exception e)
               {
                   println "WARNING: Se intenta transformar un valor con mal formato: '" + params.(transform.owner.owner.id+transform.path) + "'"
               }
           }
           else
           {
               println "Params no tiene la path: " + transform.owner.owner.id + transform.path
           }
       }
            
       //render(view:'showParams')
       
       // params es GrailsParameterMap y bind espera LinkedHashMap
       def pathValue = [:]
       
       params.keySet().each{
           println "   (=) " + it.getClass().getSimpleName()
           if (it.startsWith('openEHR'))
              pathValue[it] = params[it]
       }
       /*
       pathValue.remove('controller')
       pathValue.remove('action')
       pathValue.remove('templateId')
       pathValue.remove('doit')
       */
       
       // Pongo archivos (puede no venir ninguno)
       pathValue += files
       
       //test binder
       XStream xstream = new XStream()
       BindingAOMRM bindingAOMRM = new BindingAOMRM()
       def rmobj = bindingAOMRM.bind(pathValue, params.templateId)
        
       //println "Params: " + params.toString() + "\n"
       //println "Path value: " + pathValue + "\n"
       println "Errors: " + bindingAOMRM.getErrores() + "\n"
       println "Errors2: " + bindingAOMRM.getErrors2() + "\n"

       
       println xstream.toXML(rmobj)


       if (rmobj)
       {
           if (!rmobj.save())
           {
                println "ERROR AL SALVAR: ---> " + rmobj.errors
           }
           else
           {
               println "SALVADO OK"
               
               redirect(action: 'generarShow',
                        params: [id:rmobj.id]
                       )
               return
           }
       }
       else
       {
           // volver a la pagina y pedirle que ingrese algun dato
           println "EL RESULTADO DEL BINDEO ES NULL"
       }

       render( text: xstream.toXML(rmobj), contentType:'text/xml' )
    }
    
   /**
    * in: id identificador del locatable
    */
    def generarShow = {
        return [rmNode:Locatable.get(params.id)]
    }
}
